<template>
	<view class="drag-wrap">
		<movable-area class="drag-area" :style="{height: `${areaHeight}px`,width:`${areaWidth}px`}">
			<movable-view 
				class="drag-item" 
				:class="{moveing:item.moveing}"
				direction="all" 
				:x="item.x" 
				:y="item.y"
				@change="onChage($event, item)" 
				@touchstart="onTouchstart($event, item)" 
				@touchend="onTouchend($event, item)"
				v-for="item in list"
				:key="item.id"
				:style="{width:`${cellSize}px`,height:`${cellSize}px`,zIndex:item.zIndex}"
			>
				<view class="item-box">
					<slot name="default" :info="item.info" :mid="item.id">
						{{item.id}}
					</slot>
				</view>
			</movable-view>
			
			<movable-view 
				class="drag-item"
				direction="all" 
				v-if="openAdd"
				:disabled="true"
				:x="addLayout.x" 
				:y="addLayout.y" 
				:style="{width:`${cellSize}px`,height:`${cellSize}px`,zIndex:0}"
			>
				<slot name="add"></slot>
			</movable-view>
		</movable-area>
	</view>
</template>

<script>
	export default{
		props:{
			column:{ 
				type:Number,
				default:3
			},
			openAdd:{ 
				type:Boolean,
				default:false
			}
		},
		data(){
			return{
				
				areaWidth: 0, 
				
				
				list:[]
			}
		},
		computed:{
			cellSize(){
				return this.areaWidth/this.column
			},
			areaHeight(){
				if(this.openAdd){
					return Math.ceil((this.list.length+1)/this.column)*this.cellSize
				}else{
					return Math.ceil(this.list.length/this.column)*this.cellSize
				}
			},
			addLayout(){
				return{
					x:(this.list.length%3)*this.cellSize,
					y:Math.floor(this.list.length/3)*this.cellSize
				}
			}
		},
		mounted() {
			const query = uni.createSelectorQuery().in(this)
			query.select('.drag-wrap').boundingClientRect(({width}) => {
				this.areaWidth = width
				this.$nextTick(()=>{
					this.list.forEach((item)=>{
						this.moveItem(item,0)
					})
				})
			})
			query.exec()
		},
		methods:{
			onChage({detail:{x,y,source}},item){
				if(source!='touch'){
					return
				}
				if(!item.moveing){ 
					return
				}
				item.oldX = x
				item.oldY = y
				const index = Math.floor((y/this.cellSize)+0.5)*this.column+Math.floor((x/this.cellSize)+0.5)
				if(index==item.index||index>=this.list.length){
					return
				}
				this.list.forEach((obj)=>{
					if(item.index > index && obj.index >= index && obj.index < item.index){
						this.moveItem(obj, 1)
					}else if(item.index < index && obj.index <= index && obj.index > item.index){
						this.moveItem(obj, -1)
					}
				})
				item.index = index
			},
			onTouchstart(e,item){
				item.moveing = true
				item.zIndex = 2
				this.list.forEach((sub)=>{
					if(sub.id!=item.id){
						sub.zIndex = 1
					}
				})
				
			},
			onTouchend(e,item){
				item.moveing = false
				item.x = item.oldX
				item.y = item.oldY
				this.$nextTick(()=>{
					item.x = (item.index%this.column)*this.cellSize
					item.y = Math.floor(item.index/this.column)*this.cellSize
					this.emitSortList()
				})
			},
			moveItem(item,step){ 
				item.index += step
				
				item.x = (item.index%this.column)*this.cellSize
				item.y = Math.floor(item.index/this.column)*this.cellSize
				
			},
			batchAdd(list=[]){
				list.forEach((item)=>{
					this.oneAdd(item)
				})
			},
			oneAdd(info){
				const idx = this.list.length
				this.list.push({
					info:info,
					id:info.id,
					index:idx,
					x:(idx%this.column)*this.cellSize,
					y:Math.floor(idx/this.column)*this.cellSize,
					zIndex:1,
					moveing:false
				})
			},
			remove(id){
				const idx = this.list.findIndex((item)=>item.id == id)
				this.list.splice(idx,1)
				this.list.forEach((item)=>{
					if(item.index>idx){
						item.index -= 1
						item.x = (item.index%this.column)*this.cellSize
						item.y = Math.floor(item.index/this.column)*this.cellSize
					}
				})
			},
			clear(){
				this.list = []
			},
			emitSortList(){
				const list = this.list.slice().sort((a, b) =>a.index - b.index).map(({info})=>info)
				this.$emit('change',list)
			}
		}
	}
</script>

<style lang="scss" scoped>
	.drag-area{
		width: 100%;
		height: 750rpx;
		.drag-item{
			
			.item-box{
				width: 100%;
				height: 100%;
			}
			&.hide{
				display: none;
			}
			&.moveing{
				.item-box{
					transform: scale(1.1);
					opacity: 0.8;
				}
			}
		}
	}
</style>